package com.jeesite.modules.wx.web;


import com.jeesite.modules.common.*;
import com.jeesite.modules.common.StringUtils;
import com.jeesite.modules.common.refun.StringUtil;
import com.jeesite.modules.wx.entity.*;
import com.jeesite.modules.wx.service.WxActivityService;
import com.jeesite.modules.wx.service.WxPayService;
import com.jeesite.modules.wx.service.WxUserDisValueRecordService;
import com.jeesite.modules.wx.service.WxUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.*;

@RequestMapping("/wx")
@RestController
@Slf4j
public class PayController {

    private static final String mchId = "1504722971";
    private static final String key = "ZRgZoUq5b0MKkO5gDWyc1MNQCdGHu5cK";
    private static String AppID = "wxc86ac9d5537decf6";


    @Autowired
    private WxActivityService wxActivityService;
    @Autowired
    private WxUserDisValueRecordService wxUserDisValueRecordService;
    @Autowired
    private WxUserService wxUserService;

    @Autowired
    private WxPayService wxPayService;

    @RequestMapping("/pay")
    public Response<Map<String,Object>> pay(String activityId, String userOpenId,
                                           @RequestParam(value = "inviteUserOpenId",required = false) String inviteUserOpenId,
                                            @RequestParam(value = "phone",required = false) String phone,
                                            @RequestParam(value = "username",required = false) String userName,HttpServletRequest request){
        Response response = new Response();
        log.info("phone={}",phone);
        log.info("inviteUserOpenId={}",inviteUserOpenId);
        log.info("inviteUserOpenId={}", org.apache.commons.lang3.StringUtils.isNotEmpty(inviteUserOpenId));
        log.info("inviteUserOpenId={}", org.apache.commons.lang3.StringUtils.isEmpty(inviteUserOpenId));

        //查询活动的价格
        WxActivity wxActivity = wxActivityService.get(activityId);
        if(null == wxActivity){
            log.error("活动={}不存在",activityId);
            response.setErrorMessage("活动不存在");
            return response;
        }
        String price = wxActivity.getPrice();
        log.info("支付获得活动的价格={}",price);

        //查询活动是否过期
        Date activityDate = wxActivity.getEndTime();
        if(new Date().after(activityDate)){
            log.error("活动={}过期",activityId);
            response.setErrorMessage("活动已经过期");
            return response;
        }

        //获得用户次数
//        WxUser wxUser = new WxUser();
//        wxUser.setWxOpenId(userOpenId);
//        List<WxUser> wxUserList = wxUserService.findList(wxUser);
//        if(CollectionUtils.isNotEmpty(wxUserList)){
//            payTimes = wxUserList.size();
//        }
        //查询用户买了几次
        int payTimes = 0;
        WxUserDisValueRecord wxUserDisValueRecord = new WxUserDisValueRecord();
        wxUserDisValueRecord.setBuyUserOpenId(userOpenId);
        wxUserDisValueRecord.setBuyActivityId(Long.valueOf(activityId));
        wxUserDisValueRecord.setBuyFlag(1);
        List<WxUserDisValueRecord> wxUserDisValueRecordList = wxUserDisValueRecordService.findList(wxUserDisValueRecord);
        if(CollectionUtils.isNotEmpty(wxUserDisValueRecordList)){
            payTimes = wxUserDisValueRecordList.size();
        }
        log.info("db payTimes={}",payTimes);

        //微信活动是否限购一次
        Long oneTime = wxActivity.getOneTime();
        if(oneTime == 0){
            //代表未开启，需要获得该用户总共买了几次
            ++payTimes;
            log.info("计算后的payTimes={}",payTimes);
        }else if(oneTime == 1){
            //限购了，超过1提示失败
            if(payTimes >= 1){
                response.setErrorMessage("该活动只能购买一次");
                return response;
            }
        }

//        String payRedirectUrl = "http://api.wangjianxin.top/wx/redirect/pay?activityId="+activityId+"&inviteUserOpenId="+inviteUserOpenId+"";
        String payRedirectUrl = "http://api.wangjianxin.top/wx/redirect/pay";
        try {
            response.setData(getH5Param(wxActivity.getTitle(),wxActivity.getId(),String.valueOf(payTimes),new BigDecimal(price),userOpenId,payRedirectUrl,request));
            response.setSuccess(true);
        } catch (Exception e) {
            log.error("微信支付获取H5param失败");
            e.printStackTrace();
            response.setSuccess(false);
            response.setErrorMessage("微信支付获取H5param失败");
        }

        //保存用户订单
        log.info("pay获得参数={}",response.getData());


        WxUser wxUser = wxUserService.findByOpenId(userOpenId);

        //查询用户是否存在购买该活动无效的状态有的话不需要继续下面逻辑
        WxUserDisValueRecord findNoEffect = new WxUserDisValueRecord();
        //购买的用户
        findNoEffect.setBuyUserOpenId(userOpenId);
        //购买的活动
        findNoEffect.setBuyActivityId(Long.valueOf(activityId));
        //无效状态
        findNoEffect.setBuyFlag(0);
        List<WxUserDisValueRecord> findNoEffectList = wxUserDisValueRecordService.findList(findNoEffect);
        if(CollectionUtils.isNotEmpty(findNoEffectList)){
            //有记录，无需操作
            log.info("用户存在购买当前获得的无效订单");

            //如果有邀请人，更新邀请人，不管之前扫过谁的码没有付款，都是保存现在扫邀请码的用户数据
            if(org.apache.commons.lang3.StringUtils.isNotEmpty(inviteUserOpenId) && !inviteUserOpenId.equals("99")){
                //获得邀请用户的详细信息
                WxUser inviteWxUser = wxUserService.findByOpenId(inviteUserOpenId);

                //得到当前用户保存的无效订单信息
                WxUserDisValueRecord updateInviteUser = findNoEffectList.get(0);

                //得到原来无效订单信息的邀请用户
                String tempInviteOpenId = updateInviteUser.getUserOpenId();

                //修改最新的邀请用户,注意不是自己
                if(!inviteUserOpenId.equals(userOpenId)){
                    updateInviteUser.setUserId(Long.valueOf(inviteWxUser.getId()));
                    updateInviteUser.setUserOpenId(inviteUserOpenId);
                    wxUserDisValueRecordService.update(updateInviteUser);
                }
            }

        }else{

            //保存用户未支付订单，回调成功之后会修改订单状态
            WxUserDisValueRecord saveDisValueOrder = new WxUserDisValueRecord();
            //购买用户的userId
            saveDisValueOrder.setBuyUserId(Long.valueOf(wxUser.getId()));
            //购买用户的openId
            saveDisValueOrder.setBuyUserOpenId(userOpenId);
            //购买的活动id
            saveDisValueOrder.setBuyActivityId(Long.valueOf(activityId));
            //购买的价格
            saveDisValueOrder.setBuyPrice(new BigDecimal(price));

            try {
                saveDisValueOrder.setDisMoneyValue(new BigDecimal(wxActivity.getDisValue()));
            }catch (Exception e){
                saveDisValueOrder.setDisMoneyValue(new BigDecimal("0"));
            }
            //涉及返佣
            if(org.apache.commons.lang3.StringUtils.isNotEmpty(inviteUserOpenId) && !inviteUserOpenId.equals("99")){
                //涉及分享购买
                log.info("用户={},购买活动={}带有邀请用户={}",userOpenId,activityId,inviteUserOpenId);
                WxUser inviteWxUser = wxUserService.findByOpenId(inviteUserOpenId);
                if(null == inviteWxUser){
                    log.error("查询邀请用户为空");
                }
                //排除自己
                if(!inviteUserOpenId.equals(wxUser.getWxOpenId())){
                    saveDisValueOrder.setUserId(Long.valueOf(inviteWxUser.getId()));
                    saveDisValueOrder.setUserOpenId(inviteWxUser.getWxOpenId());
                }

                saveDisValueOrder.setBuyFlag(0);
            }
            log.info("saveDisValueOrder price ={}",saveDisValueOrder.getBuyPrice());
            log.info("saveDisValueOrder getDisMoneyValue ={}",saveDisValueOrder.getDisMoneyValue());
            wxUserDisValueRecordService.insert(saveDisValueOrder);
        }

        //保存用户支付的手机号
        if(StringUtil.isNotEmpty(phone)){
            wxUser.setPhone(phone);
            wxUser.setUserName(userName);
            wxUserService.update(wxUser);
        }

        return response;
    }

    /**
     * 微信支付回调
     */
    @RequestMapping("/redirect/pay")
    public void redirect(HttpServletRequest request, HttpServletResponse response,
                         @RequestParam(value = "activityId",required = false) String activityId) throws Exception {
        log.info("支付成功后进去的回调start，获得参数activityId={},获得参数inviteUserOpenId={}",activityId);

        BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream) request.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        //sb为微信返回的xml
        String notityXml = sb.toString();
        String resXml = "";
        log.info("接收到的报文：{}", notityXml);
        Map map = PayUtil.doXMLParse(notityXml);
        String returnCode = (String) map.get("return_code");
        if ("SUCCESS".equals(returnCode)) {
            String msg = "success";
            response.setContentType("text/xml");
            //验证签名是否正确
            log.info("成功");
            if (PayUtil.verify(PayUtil.createLinkString(map), (String) map.get("sign"), key, "utf-8")) {

                /**此处添加自己的业务逻辑代码start**/
                log.info("-----------------进入业务逻辑-----------------------");
                String openId = (String) map.get("openid");
                activityId = (String) map.get("out_trade_no");
                log.info("获取解析的保温活动id和次数={}",activityId);


                String[] arrayActiviryAndTimes = activityId.split("\\|");
                log.info("--进入业务逻辑--获得activityId={}",arrayActiviryAndTimes[0]);
                log.info("--进入业务逻辑--获得openId={}",openId);

                //执行支付下单逻辑,修改订单状态
                Integer stateResult = wxPayService.saveOrder(arrayActiviryAndTimes[0],openId,arrayActiviryAndTimes[1],request,response);


                /**此处添加自己的业务逻辑代码end**/
                //通知微信服务器已经支付成功
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                if (stateResult != 1) {
                    log.info("订单状态修改失败，--------------------------------------{}", activityId);
                    resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                            + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                }
            } else {
                resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                        + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                log.info("失败");
            }
            log.info("resXml{}", resXml);
            log.info("微信支付回调数据结束", resXml);

            BufferedOutputStream out = new BufferedOutputStream(
                    response.getOutputStream());
            out.write(resXml.getBytes());
            out.flush();
            out.close();
            response.getWriter().println(msg);
        }

    }


    public Map<String, Object> getH5Param(String orderName, String activityId,String times,BigDecimal payPrice, String openId, String notifyUrl, HttpServletRequest request) throws Exception {

        //商户订单号
        String uni = RandCharsUtils.getRandomString(9);
        int len = openId.length();
        if(len > 11){
            uni = openId.substring(6,10);
        }



        String orderId = activityId+"|"+times+"|"+uni+RandCharsUtils.getRandomString(4);
        log.info("生成商户订单id={}",orderId);

        Integer paymoneyint=payPrice.multiply(new BigDecimal(100)).intValue();
        String payMoney=paymoneyint.toString();
        log.info("支付金额:{}",payMoney);
        //生成随即字符串
        String nonce_str = StringUtils.getRandomStringByLength(32);
        //商品名称
        String body = orderName;
        //获取用户IP
        String spbill_create_ip = IpUtil.getIpAddr(request);
//        String orderId = OrderIdUtils.getOrderNo();


        Map<String, String> packageParams = new HashMap<String, String>();
        packageParams.put("appid", AppID);
        packageParams.put("mch_id", mchId);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("out_trade_no",orderId );//商户订单号
        packageParams.put("total_fee", payMoney);//支付金额，这边需要转成字符串类型，否则后面的签名会失败
        packageParams.put("notify_url", notifyUrl);//支付成功后的回调地址
        packageParams.put("trade_type", WxPayConfig.TRADETYPE);//支付方式
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("openid", openId);


        String preStr = PayUtil.createLinkString(packageParams);
        //MD5运算生成签名，用于调用微信支付统一接口;
        String mySign = PayUtil.sign(preStr,key,"utf-8").toUpperCase();
        //

        String xml = "<xml>" + "<appid>" + AppID + "</appid>"
                + "<body><![CDATA[" + body + "]]></body>"
                + "<mch_id>" + mchId + "</mch_id>"
                + "<nonce_str>" + nonce_str + "</nonce_str>"
                + "<notify_url>" + notifyUrl + "</notify_url>"
                + "<openid>" + openId + "</openid>"
                + "<out_trade_no>" + orderId + "</out_trade_no>"
                + "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>"
                + "<total_fee>" + payMoney + "</total_fee>"
                + "<trade_type>" + WxPayConfig.TRADETYPE + "</trade_type>"
                + "<sign>" + mySign + "</sign>"
                + "</xml>";
        log.info("调试模式_统一下单接口 请求XML数据：{}",xml);

        //调用统一下单接口，并接受返回的结果
        String result = PayUtil.httpRequest(WxPayConfig.pay_url, "POST", xml);

        log.info("调试模式_统一下单接口 返回XML数据：{}" , result);
        Map map = PayUtil.doXMLParse(result);
        //返回状态码
        String return_code = (String) map.get("return_code");
        log.info("返回状态码={}",return_code);
        //返回给H5端需要的参数
        Map<String, Object> response = new HashMap<String, Object>();
        if(return_code.equals("SUCCESS")){
            //返回的预付单信息
            String prepay_id = (String) map.get("prepay_id");
            response.put("nonceStr", nonce_str);
            response.put("package", "prepay_id=" + prepay_id);
            Long timeStamp = System.currentTimeMillis() / 1000;
            //这边要将返回的时间戳转化成字符串
            response.put("timeStamp", timeStamp + "");
            //拼接签名需要的参数
            String stringSignTemp = "appId=" + AppID + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id+ "&signType=MD5&timeStamp=" + timeStamp;
            //再次签名，这个签名用于H5端
            String paySign = PayUtil.sign(stringSignTemp, key, "utf-8").toUpperCase();
            response.put("paySign", paySign);
        }
        response.put("appid", AppID);


        log.info("参数map={}",response);
        return response;
    }




}
